library UnitGroup requires  /*
    */ LinkedList /*
    */ Math /*
    */ GroupUtils /*
    */ Unit /*
    */

    struct UnitGroup

        List m_unitList
        real m_x
        real m_y
        real m_radius

        static method create takes nothing returns thistype
            local thistype this = thistype.allocate()
            set this.m_unitList = List.create()
            set this.m_x = 0
            set this.m_y = 0
            set this.m_radius = 0
            return this
        endmethod

        method destroy takes nothing returns nothing
            call this.m_unitList.destroy()
            call this.deallocate()
        endmethod

        private method search takes Unit ud returns Unit
            local Link link
            local Unit tmpUd = 0
            
            if ud <= 0 then
                return 0
            endif
            set link = this.m_unitList.search(ud)
            if link > 0 and link.data > 0 then
                set tmpUd = Unit(link.data)
            endif
            return tmpUd
        endmethod

        method operator first takes nothing returns Link
            return this.m_unitList.first
        endmethod

        method operator last takes nothing returns Link
            return this.m_unitList.last
        endmethod

        method operator size takes nothing returns integer
            return this.m_unitList.size
        endmethod

        method isUnitInGroup takes Unit ud returns boolean
            if ud <= 0 then
                return false
            endif
            if search(ud) > 0 then
                return true
            endif
            return false
        endmethod

        method addUnit takes Unit ud returns thistype
            if not (isUnitInGroup(ud)) then
                call Link.create(this.m_unitList, ud)
            endif
            return this
        endmethod

        method addAll takes thistype gd returns thistype
            local Unit ud
            local Link link = gd.first
            loop
                exitwhen (link <= 0)
                set ud = Unit(link.data)
                call this.addUnit(ud)
                set link = link.next
            endloop
            return this
        endmethod

        method removeUnit takes Unit ud returns thistype
            local Link link = this.m_unitList.search(ud)
            call link.destroy()
            return this
        endmethod

        method clear takes nothing returns thistype
            call this.m_unitList.clear()
            return this
        endmethod

        private static method anon_f8197077 takes nothing returns nothing
            local Unit ud = Unit.get(GetFilterUnit())
            local thistype this = thistype(bj_groupEnumTypeId)
            call this.addUnit(ud)
        endmethod

        method enumUnits takes real x, real y, real radius returns thistype
            local boolexpr filter = Condition(function thistype.anon_f8197077)
            set bj_groupEnumTypeId = this
            set this.m_x = x
            set this.m_y = y
            set this.m_radius = radius

            call GroupEnumUnitsInArea(ENUM_GROUP, x, y, radius, filter)
            call DestroyBoolExpr(filter)
            set filter = null
            return this
        endmethod

        method getNearestUnitXY takes real x, real y, real radius returns Unit
            local Unit ud = 0
            local Unit temp = 0
            local real dis = radius + 1
            local real dis2 = 0
            local Link link = this.first
            loop
                exitwhen (link <= 0)
                set temp = Unit(link.data)
                set dis2 = GetDistanceByXY(x, y, GetUnitX(temp.m_unit), GetUnitY(temp.m_unit))
                if dis2 < dis then
                    set dis = dis2
                    set ud = temp
                endif
                set link = link.next
            endloop
            return ud
        endmethod

        method getNearestUnit takes nothing returns Unit
            if this.m_radius > 0 then
                return getNearestUnitXY(this.m_x, this.m_y, this.m_radius)
            endif
            return 0
        endmethod

        /*
        --------------------------------------------------------------------------
        # 抓取范围内的所有单位
        --------------------------------------------------------------------------
        * param real x
        * param real y
        * param real radius
        *
        */
        static method fromArea takes real x, real y, real radius returns thistype
            local thistype g = thistype.create()
            return g.enumUnits(x, y, radius)
        endmethod

    endstruct

endlibrary